#include <stdio.h>
#include "user.h"
#include "cloud.h"

void insert_num(User *u, CloudServer *c, int s) {
    //用户插入数据函数
    memset(u->Px->Px_coef, 0, sizeof(u->Px->Px_coef));
    int hash_number = murmurhash(s, u); //先找到这个元素要放到哪个位置
    int root_num = u->my_num_table->num[hash_number]; //这个桶里需要被除掉的随机数根
    int root = u->my_root_table->r_table[hash_number]->root[root_num];
    getFromCloud(c, u, u->my_Hashtable->HT[hash_number]->randomId, hash_number);

    /*----------------- 多项式除法---------------*/

    long long result[BUCKET_SIZE + 1] = {0};
    long long temp_p[BUCKET_SIZE] = {0};
    temp_p[BUCKET_SIZE-1] = u->Px->Px_coef[BUCKET_SIZE]; //设置最高次项
    for (size_t i = BUCKET_SIZE-1; i > 0; i--) {
        temp_p[i - 1] = u->Px->Px_coef[i] + root * temp_p[i];
    }

    /*----------------- 多项式除法---------------*/

    

    /*----------------- 多项式乘法---------------*/
    // 对每一项执行乘法
    for (int i = BUCKET_SIZE-1; i >= 0; i--) {
        result[i + 1] += temp_p[i];
        result[i] -= temp_p[i] * (s);
    }
    for (size_t i = 0; i < BUCKET_SIZE + 1; i++) {
        u->Px->Px_coef[i] = result[i];
    }
    /*----------------- 多项式乘法---------------*/

    

    divide_and_send_polynomial(c, u, hash_number); //将插入完成后的新桶分发给用户和云平台。

    u->my_num_table->num[hash_number] += 1; // 更新一下桶里面元素的数量。
}


void delete_num(User *u, CloudServer *c, int s) {
    //用户删除数据函数
    memset(u->Px->Px_coef, 0, sizeof(u->Px->Px_coef));
    int hash_number = murmurhash(s,u); //先找到这个被删除的元素在表中哪个位置
    int root_num = u->my_num_table->num[hash_number]; //这个桶里需要被恢复的随机数根

    getFromCloud(c, u, u->my_Hashtable->HT[hash_number]->randomId, hash_number);

   

    /*----------------- 多项式除法---------------*/
    long long temp_p[BUCKET_SIZE] = {0};
    long long result[BUCKET_SIZE + 1] = {0};
    int root_value = (rand() % 5) + 1; //产生一个新的随机数
    u->my_root_table->r_table[hash_number]->root[u->my_num_table->num[hash_number]] = root_value; //将该随机数填充到随机数根表当中

    temp_p[BUCKET_SIZE-1] = u->Px->Px_coef[BUCKET_SIZE]; //设置最高次项
    for (size_t i = BUCKET_SIZE-1; i > 0; i--) {
        temp_p[i - 1] = u->Px->Px_coef[i] + s * temp_p[i];
    }

    /*----------------- 多项式除法---------------*/

    /*printf("删除操作执行中，被除后的多项式为\n");
    for (size_t i = 0; i < 10; i++) //检查一下运行效果，这里是除法阶段
    {
        printf("%d x^%d + ", temp_p[i], i);
    }
    printf("\n");

    /*----------------- 多项式乘法---------------*/
    // 对每一项执行乘法*/

    for (int i = BUCKET_SIZE - 1; i >= 0; i--) {
        result[i + 1] += temp_p[i];
        result[i] -= temp_p[i] * (root_value);
    }
    for (size_t i = 0; i < BUCKET_SIZE + 1; i++) {
        u->Px->Px_coef[i] = result[i];
    }

    /*----------------- 多项式乘法---------------*/

    divide_and_send_polynomial(c, u, hash_number); //将插入完成后的新桶分发给用户和云平台。
    for (size_t i = 0; i < TABLE_SIZE + 1; i++) {
        u->Px->Px_coef[i] = 0;
    }
    u->my_num_table->num[hash_number] -= 1; // 更新一下桶里面元素的数量。
}


void RIE(User *A, User *B, CloudServer *C) {
    //这个函数就是两个用户之间查看是否存在元素交集

    //我们让用户A扮演真正实施查找操作的角色,让用户B扮演委托查找的角色

    /*---------------------------------初始化过程------------------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) //委托用户A随机生成两个随机多项式
    {
        for (size_t j = 0; j < W_NUM + 1; j++) {
            A->my_w_table->wx_table[0][i]->wx_coef[j] = (rand() % 5) + 1; //给A的随机多项式赋值
            A->my_w_table->wx_table[1][i]->wx_coef[j] = (rand() % 5) + 1; //给B的随机多项式赋值
        }
    }


    for (size_t i = 0; i < TABLE_SIZE; i++) {
        //用户B自己生成Z_B_0和Z_B_1
        for (size_t j = 0; j < BUCKET_SIZE + 1; j++) {
            B->secret_share_table->z_secret_table[0][i]->zx_coef[j] =  rand()% 10000;
            B->secret_share_table->z_secret_table[1][i]->zx_coef[j] = B->my_z_table->ztable[i]->zx_coef[j] - B->secret_share_table->z_secret_table[0][i]->zx_coef[j];
        }
        B->secret_share_table->z_secret_table[0][i]->randomId = B->my_z_table->ztable[i]->randomId;
        B->secret_share_table->z_secret_table[1][i]->randomId = B->my_z_table->ztable[i]->randomId;
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) //委托用户A生成两个用户的随机标识矩阵
    {
        A->label_matrix[0][i] = A->my_z_table->ztable[i]->randomId;
        A->label_matrix[1][i] = B->my_z_table->ztable[i]->randomId;
    }

    /*---------------------------------初始化过程------------------------------------------*/

    /*-----------------------将Z_B_0发送给云平台C的过程----------------------------*/

    for (size_t j = 0; j < TABLE_SIZE; j++) //云平台中C找对应的桶 j
    {
        for (size_t k = 0; k < TABLE_SIZE; k++) //用户B找对应的桶 k
        {
            if (C->user_o_hat_table[B->User_symbol]->ohat[j]->randomId == B->my_z_table->ztable[k]->randomId)
            //查看随机标识是否对应
            {
                for (size_t i = 0; i < BUCKET_SIZE + 1; i++) //将云平台对应的桶中填充为用户的秘密分享信息
                {
                    C->user_z_table[B->User_symbol]->ztable[j]->zx_coef[i] = B->secret_share_table->z_secret_table[0][k]->zx_coef[i];
                }
                C->user_z_table[B->User_symbol]->ztable[j]->randomId = B->secret_share_table->z_secret_table[0][k]->randomId; //将随机标识也赋值过去
            }
        }
    } //注意，在这里，z_B_0和ohat_B的排列顺序是一样的

    /*-----------------------将Z_B_0发送给云平台C的过程----------------------------*/

    /*-----------------------将Z_B_1发送给用户A的过程------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) {
        A->other_zx[i]->randomId = B->secret_share_table->z_secret_table[1][i]->randomId;
        for (size_t j = 0; j < BUCKET_SIZE + 1; j++) {
            A->other_zx[i]->zx_coef[j] = B->secret_share_table->z_secret_table[1][i]->zx_coef[j];
        }
    }
    //这里Z_B_1的排列顺序就是原始排列

    /*-----------------------将Z_B_1发送给用户A的过程------------------------------*/

    /*-----------------------用户A计算RIE随机编码------------------------------*/


    for (size_t i = 0; i < TABLE_SIZE; i++) // 计算zA(x)的RIE掩码部分
    {
        A->qtable->my_qtable[i]->randomId = A->my_z_table->ztable[i]->randomId; //全部使用用户A的随机标识作为认证
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                A->qtable->my_qtable[i]->qx_coef[j + k] += A->my_z_table->ztable[i]->zx_coef[j] * A->my_w_table->wx_table[0][i]->wx_coef[k];
            }
        }
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) // 计算zB(x)_1的RIE掩码部分
    {
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                A->qtable->other_qtable[i]->qx_coef[j + k] += A->other_zx[i]->zx_coef[j] * A->my_w_table->wx_table[1][i]->wx_coef[k];
            }
        }
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) //将上面计算的两部分进行合并
    {
        A->qtable->final_qtable[i]->randomId = A->qtable->my_qtable[i]->randomId;
        for (size_t j = 0; j <= BUCKET_SIZE + W_NUM; j++) {
            A->qtable->final_qtable[i]->qx_coef[j] =
                    A->qtable->my_qtable[i]->qx_coef[j] + A->qtable->other_qtable[i]->qx_coef[j];
        }
    }
    //这里计算完以后，就是原始排列顺序

    /*-----------------------用户A计算RIE随机编码------------------------------*/

    /*-----------------------用户A向云平台发送RIE过程中用到的随机多项式------------------------------*/


    for (size_t i = 0; i < TABLE_SIZE; i++) //对C中的表格进行遍历搜寻
    {
        for (size_t j = 0; j < TABLE_SIZE; j++) //对用户A中的表格进行遍历搜寻
        {
            if (C->user_o_hat_table[A->User_symbol]->ohat[i]->randomId == A->label_matrix[0][j]) {
                for (size_t k = 0; k < W_NUM + 1; k++) {
                    C->cloud_w_table->wx_table[0][i]->wx_coef[k] = A->my_w_table->wx_table[0][j]->wx_coef[k];
                }
            }
        }

        for (size_t j = 0; j < TABLE_SIZE; j++) //对用户B中的表格进行遍历搜寻
        {
            if (C->user_o_hat_table[B->User_symbol]->ohat[i]->randomId == A->label_matrix[1][j]) {
                for (size_t k = 0; k < W_NUM + 1; k++) {
                    C->cloud_w_table->wx_table[1][i]->wx_coef[k] = A->my_w_table->wx_table[1][j]->wx_coef[k];
                }
            }
        }
    }

    /*-----------------------用户A向云平台发送RIE过程中用到的随机多项式------------------------------*/

    /*-----------------------云平台计算RIE随机编码------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) //把用户B传输过来的z_B_0和在云平台存储的ohat_B加和到一起
    {
        for (size_t j = 0; j < BUCKET_SIZE + 1; j++) {
            C->temp_result[i][j] = C->user_o_hat_table[B->User_symbol]->ohat[i]->ox_coef[j] + C->user_z_table[B->User_symbol]->ztable[i]->zx_coef[j];
        }
    }//现在是B 的 ohat的顺序

    for (size_t i = 0; i < TABLE_SIZE; i++) //先用w_A对A的ohat进行掩码操作，计算A的t值
    {
        C->cloud_t_table->User_A_t_table[i]->randomId = C->user_o_hat_table[A->User_symbol]->ohat[i]->randomId;
        //全部使用用户A的随机标识作为认证
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                C->cloud_t_table->User_A_t_table[i]->tx_coef[j + k] += C->user_o_hat_table[A->User_symbol]->ohat[i]->ox_coef[j] * C->cloud_w_table->wx_table[0][i]->wx_coef[k];
            }
        }
    }//这里现在是A的ohat 顺序

    for (size_t i = 0; i < TABLE_SIZE; i++) //云平台计算用户B的t值
    {
        C->cloud_t_table->User_B_t_table[i]->randomId = C->user_o_hat_table[B->User_symbol]->ohat[i]->randomId;
        //将随机标识传递过去
        for (size_t j = 0; j <= BUCKET_SIZE; j++) {
            for (size_t k = 0; k <= W_NUM; k++) {
                C->cloud_t_table->User_B_t_table[i]->tx_coef[j + k] += C->temp_result[i][j] * C->cloud_w_table->wx_table[1][i]->wx_coef[k]; //用刚刚计算的结果进行计算
            }
        }
    }

    for (size_t i = 0; i < TABLE_SIZE; i++) //对用户A的随机标识进行查找
    {
        for (size_t j = 0; j < TABLE_SIZE; j++) //对用户B的随机标识进行查找
        {
            for (size_t k = 0; k < TABLE_SIZE; k++) //在A用户生成的标识矩阵中进行比对
            {
                if (C->cloud_t_table->User_A_t_table[i]->randomId == A->label_matrix[0][k] && C->cloud_t_table->
                    User_B_t_table[j]->randomId == A->label_matrix[1][k]) {
                    for (size_t p = 0; p < BUCKET_SIZE + W_NUM + 1; p++) {
                        C->cloud_t_table->final_t_table[k]->tx_coef[p] = C->cloud_t_table->User_A_t_table[i]->tx_coef[p] + C->cloud_t_table->User_B_t_table[j]->tx_coef[p];
                    }
                }
            }
        }
    }

    /*-----------------------云平台计算RIE随机编码------------------------------*/

    /*-----------------------用户B接收用户A和云平台的输出------------------------------*/

    for (size_t i = 0; i < TABLE_SIZE; i++) {
        for (size_t j = 0; j < BUCKET_SIZE + W_NUM + 1; j++) {
            B->my_rie_table->my_rie_table[i]->rie_x_coef[j] =
                    C->cloud_t_table->final_t_table[i]->tx_coef[j] + A->qtable->final_qtable[i]->qx_coef[j];
        }
    }

    /*-----------------------用户B接收用户A和云平台的输出------------------------------*/
}

void check_RIE(User *u, int s) //检查是否存在共同存有的元素
{
    int hash = murmurhash(s, u); //先找这个元素应该在哪个桶里
    long long result = 0; //初始化一个结果，先将其置为0
    for (size_t i = 0; i < BUCKET_SIZE + W_NUM + 1; i++) {
        long long temp = power(s, i);
        result += u->my_rie_table->my_rie_table[hash]->rie_x_coef[i] * temp;
    }
    if (result == 0) {
        printf("该元素存在。");
    } 
    else {
        printf("该元素不存在。");
    }
}


/*------------------------这里写的是用户掉线以后，其他用户利用sss来进行隐私求交的过程-----------------------------*/


void generate_ss_table(User *u){//这是一个初始化秘密分享表的函数

    for (size_t i = 0; i < SHARE_SIZE; i++)//这是在6份分享里面遍历
    {
        u->my_ss_table[i]->share_num = i; //这里是对每个份额进行标识

        for (size_t j = 0; j < TABLE_SIZE; j++)//这是在哈希表里遍历
        {
            u->my_ss_table[i]->ss_table[j]->randomId = u->my_z_table->ztable[j]->randomId; //把RandomId也对应过来，用于到时候对应
            
            for (size_t k = 0; k < BUCKET_SIZE+1; k++)//这是在桶里面遍历
            {
               u->my_ss_table[i]->ss_table[j]->z_ss_x_coef[k] = 0
            }
        }

    }
}

void create_secret_share(User *u){//用户将自己的z(x)变为6份秘密分享的函数

    for (int i = 0; i < TABLE_SIZE; i++) {
        for (int j = 0; j < BUCKET_SIZE; j++) {
            int sum = 0;
            // 为前5份生成随机数
            for (int k = 0; k < SHARE_SIZE - 1; k++) {
                u->my_ss_table[k]->ss_table[i]->z_ss_x_coef[j] = rand() % 10000; // 随机数范围 0-10000
                sum += u->my_ss_table[k]->ss_table[i]->z_ss_x_coef[j];
            }

            // 第6份通过原始值减去前5份的和计算得到
            u->my_ss_table[SHARE_SIZE-1]->ss_table[i]->z_ss_x_coef[j] = u->my_z_table->ztable[i]->zx_coef[j] - sum;
        }
    }
}

void create_share_symbol(User *u){//这个函数帮助用户生成他的share_symbol表格

//这里不能这么简单来写，得考虑每个用户需要按照不同的用户顺序来分发自己的share
//得根据云平台的用户表来写
    u->share_symbol[0][0]=
    

}







/*------------------------这里写的是用户掉线以后，其他用户利用sss来进行隐私求交的过程-----------------------------*/